import random


def generate_random_word(min_length=1, max_length=5):
    word = ""
    target_length = random.randint(min_length, max_length)

    for i in range(0, target_length):
        word += chr(random.randint(97, 122))

    return word


def generate_random_nodes(root_name, children_count):
    nodes = [
        {
            "id": "0",
            "name": root_name,
            "symbolSize": 50,
            "category": 0,
            "symbol": "roundRect"
        }
    ]

    for i in range(0, children_count):
        nodes.append({
            "id": i + 1,
            "name": generate_random_word(),
            "symbolSize": 30,
            "category": 1
        })

    return nodes


def generate_random_links(children_count, node_max_son_count=5):
    remaining_children_count = children_count
    current_child_index = 1

    current_father_indexes = [0]

    is_at_root = True

    links = []

    # add children iteratively, level by level
    while remaining_children_count > 0:
        next_father_indexes = []

        for i in current_father_indexes:
            if remaining_children_count <= 0:
                break

            current_node_target_children_count = random.randint(1, node_max_son_count)
            if is_at_root:
                current_node_target_children_count = node_max_son_count
                is_at_root = False

            current_node_target_children_count = \
                min(current_node_target_children_count, remaining_children_count)

            for j in range(current_child_index,
                           current_child_index + current_node_target_children_count):
                links.append({
                    "source": i,
                    "target": j,
                    "label": {
                        "show": True
                    }
                })

                next_father_indexes.append(j)

            remaining_children_count -= current_node_target_children_count
            current_child_index += current_node_target_children_count

        current_father_indexes = next_father_indexes

    return links


def generate_random_graph(root_name, min_children_count=5, max_children_count=35):
    children_count = random.randint(min_children_count, max_children_count)
    data = {
        "nodes": generate_random_nodes(root_name, children_count),
        "links": generate_random_links(children_count),
        "categories": [
            {
                "name": "A"
            },
            {
                "name": "B"
            }
        ]
    }

    return data
